#include "rep.hpp"
#include "gc.h"

namespace rep{

  size_t TypeHelper::memSize(Slot* in){return sizeof(int);}
  
  Type* TypeHelper::type(Slot* in){
    //unimplemented
    return NULL;
  }

  string* TypeHelper::toString(Slot* in){
    //unimplemented
    return NULL;
  }

  

  int TypeHelper::hashCode(Slot* in){
    static hash<int> h; 
    return h((int)in->type);
  }

  void TypeHelper::assign(Slot* to, Type* rvalue){
    to->tag = Slot::TYPE;
    to->type = rvalue;
  }

  FrameType* UnboundFrameType::bind(Slot* env){
    return new (GC) FrameType(env, numSlots, parent, bindings);
  }

  /**
   * Pop stuff off, pack it into the environment.
   */
  Cons* FrameType::packArgs(Cons* stack, Slot* frame, int howmany){
    Slot arg;
    if(bindings==NULL){
      //no standard arguments.
      return stack;
    }else{
      //put in the args
      for(int popped = 0; popped < howmany; popped++){
        assert(stack != NULL);
        stack = stack->pop(&arg);
        *FrameHelper::immDirectLookup(frame, bindings[popped]) = arg;
      }
    }
    return stack;
  }

  bool FrameType::requiresReturn(){return requiredContinuations & Slot::RETURN_FLAG;}
  bool FrameType::requiresExcept(){return requiredContinuations & Slot::EXCEPT_FLAG;}
  bool FrameType::requiresYield(){return requiredContinuations & Slot::YIELD_FLAG;}
  bool FrameType::requiresIfDone(){return requiredContinuations & Slot::IFDONE_FLAG;}
  bool FrameType::requiresCont(){return requiredContinuations & Slot::CONT_FLAG;}
  bool FrameType::requiresBreak(){return requiredContinuations & Slot::BREAK_FLAG;}
};
